DataConnectors/O365 DataCSharp/Teams.CustomConnector.Processor/Processor.cs (201 lines of code) (raw):
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Teams.CustomConnector.Common;
using Teams.CustomConnector.Models;
/// <summary>
///
/// </summary>
namespace Teams.CustomConnector.Processor
{
public class Processor
{
private string AadInstance = string.Empty;
private string TenantId = string.Empty;
private string ClientId = string.Empty;
private string ClientSecret = string.Empty;
private readonly ILogger log;
private readonly string publisherGuid = Environment.GetEnvironmentVariable(Constants.PublisherGUID);
private readonly string ContentType = Environment.GetEnvironmentVariable(Constants.ContentType);
public Processor(ILogger log)
{
this.log = log;
AadInstance = Environment.GetEnvironmentVariable(Constants.AADInstance);
TenantId = Environment.GetEnvironmentVariable(Constants.TenantId);
}
/// <summary>Processes the specified start time.</summary>
/// <param name="startTime">The start time.</param>
/// <param name="endTime">The end time.</param>
/// <returns></returns>
public async Task<List<AuditDetailedReport>> Process(string startTime, string endTime)
{
log.LogInformation(Constants.OMSRequestProcessStarted);
string urlParameters = $"?contentType=Audit.General&PublisherIdentifier={publisherGuid}&startTime={startTime}&endTime={endTime}";
string url = $"https://manage.office.com/api/v1.0/" + TenantId + "/activity/feed/subscriptions/content";
int pageCounter = 0;
List<AuditDetailedReport> FinalAuditReports = new List<AuditDetailedReport>();
AuditInitialDataObject auditInitialDataObject;
try
{
do
{
// Get teh initial data entry for the data pull
auditInitialDataObject = await GetInitialDataObject(url, urlParameters);
log.LogInformation($"Total pages count {++pageCounter}");
log.LogInformation($"Total count of initial data object {(auditInitialDataObject.AuditInitialReports == null ? 0 : auditInitialDataObject.AuditInitialReports.Count)}");
if (auditInitialDataObject.AuditInitialReports == null)
{
log.LogWarning("No Audit Logs Found");
return FinalAuditReports;
}
// Get the next page URI to form the next parameter call
if (auditInitialDataObject.AuditNextPageUri != "")
urlParameters = "?" + auditInitialDataObject.AuditNextPageUri.Split('?')[1];
//List of JSON objects from the initial data call
List<AuditInitialReport> auditInitialReports = auditInitialDataObject.AuditInitialReports;
// parallal request to improve performance
int maxCalls = 1;
Parallel.ForEach(auditInitialReports, new ParallelOptions { MaxDegreeOfParallelism = maxCalls }, async (auditInitialReport) =>
{
List<AuditDetailedReport> auditDetailReports = await GetAuditDetailDataAsync(auditInitialReport.ContentUri);
//If teams is configured
var logs = auditDetailReports.Where(x => x.RecordType == "25").ToList();
FinalAuditReports.AddRange(auditDetailReports);
});
} while (auditInitialDataObject.AuditNextPageUri != "");
log.LogInformation(Constants.OMSRequestProcessCompleted);
return FinalAuditReports;
}
catch (Exception ex)
{
log.LogWarning(Constants.OMSRequestProcessFailed);
log.LogError(ex.InnerException.ToString());
throw ex;
}
}
/// <summary>Gets the authentication token.</summary>
/// <returns></returns>
private async Task<string> GetAuthToken()
{
bool.TryParse(Environment.GetEnvironmentVariable(Constants.KeyVaultEnabled), out bool isKeyVaultEnabled);
if (isKeyVaultEnabled)
{
ClientId = await KeyVaultHelper.GetKeyValueAsync(Constants.ClientId);
ClientSecret = await KeyVaultHelper.GetKeyValueAsync(Constants.ClientSecret);
}
else
{
ClientId = Environment.GetEnvironmentVariable(Constants.ClientId);
ClientSecret = Environment.GetEnvironmentVariable(Constants.ClientSecret);
}
string ResourceId = Environment.GetEnvironmentVariable(Constants.ResourceId);
var authContext = CreateAuthenticationContext();
try
{
log.LogInformation(Constants.OAuthBearerTokenGenerationStarted);
ClientCredential clientCredential = new ClientCredential(ClientId, ClientSecret);
var token = await authContext.AcquireTokenAsync(ResourceId, clientCredential);
log.LogInformation(Constants.OAuthBearerTokenGenerationCompleted);
return token.AccessToken;
}
catch (Exception ex)
{
log.LogInformation(Constants.OAuthBearerTokenGenerationFailed);
log.LogInformation(ex.InnerException.ToString());
throw ex;
}
}
/// <summary>Creates the authentication context.</summary>
/// <returns></returns>
private AuthenticationContext CreateAuthenticationContext()
{
object lockContext = new object();
AuthenticationContext context;
var authority = string.Format(CultureInfo.InvariantCulture, AadInstance, TenantId);
lock (lockContext)
{
context = new AuthenticationContext(authority);
}
return context;
}
/// <summary>Gets the initial data object.</summary>
/// <param name="ServiceUrl">The service URL.</param>
/// <param name="urlParameters">The URL parameters.</param>
/// <returns></returns>
private async Task<AuditInitialDataObject> GetInitialDataObject(string ServiceUrl, string urlParameters)
{
AuditInitialDataObject auditInitialDataObj = new AuditInitialDataObject();
try
{
List<AuditInitialReport> auditInitialReports;
// **** Call the Http Client Service ****
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(ServiceUrl);
var AuthToken = await GetAuthToken();
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + AuthToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// List data response.
log.LogInformation(Constants.OMSInitialHttpRequestSent);
HttpResponseMessage response = client.GetAsync(urlParameters, HttpCompletionOption.ResponseContentRead).Result; // Blocking call!
log.LogInformation(Constants.OMSInitialHttpRequestReceived);
string responseObj = GetResponseStream(response);
if (response.IsSuccessStatusCode)
{
log.LogInformation(Constants.OMSInitialHttpRequestSuccessful);
// Parse the response body. Blocking!
auditInitialReports = JsonConvert.DeserializeObject<List<AuditInitialReport>>(responseObj);
IEnumerable<string> values;
if (response.Headers.TryGetValues("NextPageUri", out values))
{
auditInitialDataObj.AuditNextPageUri = values.First();
auditInitialDataObj.AuditInitialReports = auditInitialReports;
}
else
{
auditInitialDataObj.AuditNextPageUri = "";
auditInitialDataObj.AuditInitialReports = auditInitialReports;
}
}
else
{
log.LogError($"{(int)response.StatusCode} ({response.ReasonPhrase})");
log.LogError(responseObj);
}
}
catch (Exception ex)
{
log.LogError(Constants.OMSInitialHttpRequestFailed);
log.LogError($"Error getting initial Audit Data. Message - {ex.Message}");
throw ex;
}
return auditInitialDataObj;
}
/// <summary>
/// Gets the response stream.
/// </summary>
/// <param name="response">The response.</param>
/// <returns></returns>
private static string GetResponseStream(HttpResponseMessage response)
{
Stream dataObjects = response.Content.ReadAsStreamAsync().Result;
StreamReader reader = new StreamReader(dataObjects);
string responseObj = reader.ReadToEnd();
return responseObj;
}
/// <summary>Gets the audit detail data.</summary>
/// <param name="url">The URL.</param>
/// <returns></returns>
private async Task<List<AuditDetailedReport>> GetAuditDetailDataAsync(string url)
{
List<AuditDetailedReport> auditDetailData = new List<AuditDetailedReport>();
try
{
log.LogInformation(Constants.OMSDetailHttpRequestSent);
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(url);
var AuthToken = await GetAuthToken();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + AuthToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// List data response.
HttpResponseMessage response = client.GetAsync("", HttpCompletionOption.ResponseContentRead).Result; // Blocking call!
log.LogInformation(Constants.OMSDetailHttpRequestReceived);
if (response.IsSuccessStatusCode)
{
log.LogInformation(Constants.OMSDetailHttpRequestSuccessful);
Stream dataObjects = response.Content.ReadAsStreamAsync().Result;
StreamReader reader = new StreamReader(dataObjects);
string responseObj = reader.ReadToEnd();
auditDetailData = JsonConvert.DeserializeObject<List<AuditDetailedReport>>(responseObj);
}
else
{
log.LogInformation(Constants.OMSDetailHttpRequestFailed);
log.LogError($"{(int)response.StatusCode} ({response.ReasonPhrase})");
}
}
catch (Exception ex)
{
log.LogError(Constants.OMSDetailHttpRequestFailed);
log.LogError($"Error getting initial Audit Data. Message - {ex.Message}");
throw ex;
}
return auditDetailData;
}
}
}